from flask import Flask, request, jsonify, render_template
from flask_cors import CORS
import json
import random
import uuid
from datetime import datetime
from db_config import Session
from models import Move, create_tables

app = Flask(__name__, static_folder='static', template_folder='templates')
CORS(app, resources={
    r"/*": {
        "origins": "*",
        "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
        "allow_headers": ["Content-Type", "Authorization"]
    }
})

# 数据库会话
session = Session()

def init_database():
    """初始化数据库表"""
    try:
        create_tables()
        print("✅ 数据库表创建成功")
    except Exception as e:
        print(f"❌ 数据库表创建失败: {e}")

def load_chess_data(state=None):
    """从数据库加载棋谱数据，可按 state 过滤"""
    try:
        if state:
            chess_data = session.query(Move).filter_by(state=state).all()
            print(f"✅ 成功加载 {len(chess_data)} 个匹配状态: {state[:20]}...")
        else:
            chess_data = session.query(Move).all()
            print(f"✅ 成功从数据库加载 {len(chess_data)} 个棋谱状态")
        return chess_data
    except Exception as e:
        print(f"❌ 加载棋谱数据失败: {e}")
        return []

def save_chess_data(state, move, move_counts=None, best_move=None):
    """保存棋谱数据到数据库"""
    try:
        existing_move = session.query(Move).filter_by(state=state).first()
        if existing_move:
            if move_counts:
                if isinstance(move_counts, dict):
                    existing_move.move_counts = json.dumps(move_counts, ensure_ascii=False)
                else:
                    existing_move.move_counts = move_counts
            if best_move:
                existing_move.best_move = best_move
        else:
            move_counts_str = json.dumps({move: 1}, ensure_ascii=False) if not move_counts else (
                json.dumps(move_counts, ensure_ascii=False) if isinstance(move_counts, dict) else move_counts
            )
            new_move = Move(
                state=state,
                best_move=best_move or move,
                move_counts=move_counts_str
            )
            session.add(new_move)
        session.commit()
        return True
    except Exception as e:
        session.rollback()
        print(f"❌ 保存棋谱数据失败: {e}")
        return False

def add_game_state(state, move):
    """添加或更新游戏状态到数据库"""
    try:
        existing_move = session.query(Move).filter_by(state=state).first()
        if existing_move:
            try:
                if isinstance(existing_move.move_counts, str):
                    move_counts = json.loads(existing_move.move_counts)
                elif isinstance(existing_move.move_counts, dict):
                    move_counts = existing_move.move_counts
                else:
                    move_counts = {}
            except (json.JSONDecodeError, TypeError):
                move_counts = {}
            
            move_counts[move] = move_counts.get(move, 0) + 1
            existing_move.move_counts = json.dumps(move_counts, ensure_ascii=False)
            session.commit()
        else:
            save_chess_data(state, move)
    except Exception as e:
        session.rollback()
        print(f"❌ 添加游戏状态时出错: {e}")

def validate_move(move_str):
    """验证移动字符串格式"""
    if not move_str or len(move_str) != 4:
        return False
    try:
        for char in move_str:
            if not char.isdigit():
                return False
        from_x, from_y, to_x, to_y = [int(char) for char in move_str]
        if not (0 <= from_x <= 8 and 0 <= from_y <= 9):
            return False
        if not (0 <= to_x <= 8 and 0 <= to_y <= 9):
            return False
        return True
    except:
        return False

def get_pieces_from_state(state):
    """从状态字符串解析出棋子位置列表"""
    pieces = []
    for i in range(0, len(state), 2):
        if i + 1 < len(state):
            x = int(state[i])
            y = int(state[i + 1])
            pieces.append([x, y])
    return pieces

def get_piece_color_by_index(piece_index):
    """根据棋子索引判断颜色"""
    return 'red' if piece_index < 16 else 'black'

def get_piece_type_by_index(piece_index):
    """根据棋子索引判断棋子类型"""
    if piece_index < 16:
        piece_types = ['车', '马', '相', '仕', '帅', '仕', '相', '马', '车', '炮', '炮', '兵', '兵', '兵', '兵', '兵']
        return piece_types[piece_index]
    else:
        black_index = piece_index - 16
        piece_types = ['车', '马', '象', '士', '将', '士', '象', '马', '车', '炮', '炮', '卒', '卒', '卒', '卒', '卒']
        return piece_types[black_index]

def is_piece_alive(piece_position):
    """检查棋子是否还在棋盘上"""
    x, y = piece_position
    return not (x == 9 and y == 9)

def is_in_palace(x, y, color):
    """检查位置是否在九宫格内"""
    if color == 'red':
        # 红方九宫格：x ∈ [3,5], y ∈ [7,9]
        return 3 <= x <= 5 and 7 <= y <= 9
    else:  # black
        # 黑方九宫格：x ∈ [3,5], y ∈ [0,2]
        return 3 <= x <= 5 and 0 <= y <= 2

def crossed_river(y, color):
    """检查是否过河"""
    if color == 'red':
        return y <= 4
    else:  # black
        return y >= 5

def find_king_position(pieces, color):
    """查找帅/将的位置"""
    king_index = 4 if color == 'red' else 20
    if king_index < len(pieces) and is_piece_alive(pieces[king_index]):
        return pieces[king_index]
    return None

def check_flying_general_after_move(pieces, moving_piece_index, from_x, from_y, to_x, to_y):
    """检查移动后是否会导致飞将 - 适用于所有棋子移动"""
    # 创建移动后的临时棋盘状态
    temp_pieces = [piece[:] for piece in pieces]
    
    # 移除被吃的棋子（如果有）
    for i, piece in enumerate(temp_pieces):
        if (i != moving_piece_index and 
            is_piece_alive(piece) and 
            piece[0] == to_x and piece[1] == to_y):
            temp_pieces[i] = [9, 9]  # 标记为被吃
            break
    
    # 执行移动
    temp_pieces[moving_piece_index] = [to_x, to_y]
    
    # 找到两个王的位置
    red_king_pos = find_king_position(temp_pieces, 'red')
    black_king_pos = find_king_position(temp_pieces, 'black')
    
    if not red_king_pos or not black_king_pos:
        return True  # 如果找不到某个王，允许移动
    
    # 检查两王是否在同一列
    if red_king_pos[0] != black_king_pos[0]:
        return True  # 不在同一列，允许移动
    
    # 两王在同一列，检查中间是否有棋子
    min_y = min(red_king_pos[1], black_king_pos[1])
    max_y = max(red_king_pos[1], black_king_pos[1])
    
    pieces_between = 0
    for y in range(min_y + 1, max_y):
        for piece in temp_pieces:
            if is_piece_alive(piece) and piece[0] == red_king_pos[0] and piece[1] == y:
                pieces_between += 1
    
    if pieces_between == 0:
        # 飞将：两王对面且中间无子，移动不合法
        return False
    
    return True  # 中间有子，允许移动

def check_flying_general_for_king_move(pieces, from_x, from_y, to_x, to_y, color):
    """检查将/帅移动时的飞将规则"""
    opponent_color = 'black' if color == 'red' else 'red'
    opponent_king_pos = find_king_position(pieces, opponent_color)
    
    if not opponent_king_pos:
        return True  # 找不到对方王，允许移动
    
    # 检查移动后是否会与对方王在同一列
    if to_x != opponent_king_pos[0]:
        return True  # 不在同一列，允许移动
    
    # 创建移动后的临时棋盘状态
    temp_pieces = [piece[:] for piece in pieces]
    
    # 找到当前王的索引并更新位置
    king_index = 4 if color == 'red' else 20
    temp_pieces[king_index] = [to_x, to_y]
    
    # 检查两王之间是否有棋子
    min_y = min(to_y, opponent_king_pos[1])
    max_y = max(to_y, opponent_king_pos[1])
    
    pieces_between = 0
    for y in range(min_y + 1, max_y):
        for piece in temp_pieces:
            if is_piece_alive(piece) and piece[0] == to_x and piece[1] == y:
                pieces_between += 1
    
    if pieces_between == 0:
        # 飞将：两王对面且中间无子
        return False
    
    return True  # 中间有子，允许移动

def can_piece_attack_position(piece_index, piece_pos, target_x, target_y, pieces):
    """检查指定棋子是否能攻击到目标位置"""
    if not is_piece_alive(piece_pos):
        return False
    from_x, from_y = piece_pos
    piece_type = get_piece_type_by_index(piece_index)
    piece_color = get_piece_color_by_index(piece_index)
    return is_valid_piece_move(piece_type, from_x, from_y, target_x, target_y, piece_color, pieces)

def is_in_check(pieces, color, _check_depth=0):
    """检查指定颜色的王是否被将军"""
    if _check_depth > 3:  # 减少递归深度限制
        return False
    
    king_pos = find_king_position(pieces, color)
    if not king_pos:
        return False
    
    king_x, king_y = king_pos
    opponent_color = 'black' if color == 'red' else 'red'
    
    for piece_index, piece_pos in enumerate(pieces):
        if (get_piece_color_by_index(piece_index) == opponent_color and 
            is_piece_alive(piece_pos)):
            if can_piece_attack_position(piece_index, piece_pos, king_x, king_y, pieces):
                return True
    return False

def get_all_valid_moves(pieces, color, _move_depth=0):
    """获取指定颜色所有可能的合法移动 - 增强飞将检查"""
    if _move_depth > 2:
        return []
    
    valid_moves = []
    
    for piece_index, piece_pos in enumerate(pieces):
        if (get_piece_color_by_index(piece_index) == color and 
            is_piece_alive(piece_pos)):
            
            from_x, from_y = piece_pos
            piece_type = get_piece_type_by_index(piece_index)
            
            # 遍历棋盘上所有位置
            for to_x in range(9):
                for to_y in range(10):
                    # 检查是否是有效移动
                    if is_valid_piece_move(piece_type, from_x, from_y, to_x, to_y, color, pieces):
                        # 检查目标位置是否被己方棋子占据
                        target_occupied_by_self = False
                        for other_index, other_pos in enumerate(pieces):
                            if (other_index != piece_index and 
                                is_piece_alive(other_pos) and 
                                other_pos[0] == to_x and other_pos[1] == to_y and
                                get_piece_color_by_index(other_index) == color):
                                target_occupied_by_self = True
                                break
                        
                        if target_occupied_by_self:
                            continue
                        
                        # 检查移动后是否会导致飞将
                        if not check_flying_general_after_move(pieces, piece_index, from_x, from_y, to_x, to_y):
                            continue
                        
                        # 模拟移动后检查是否会导致自己被将军
                        pieces_copy = [pos[:] for pos in pieces]
                        
                        # 移除被吃的棋子
                        for other_index, other_pos in enumerate(pieces_copy):
                            if (other_index != piece_index and 
                                is_piece_alive(other_pos) and 
                                other_pos[0] == to_x and other_pos[1] == to_y):
                                pieces_copy[other_index] = [9, 9]
                                break
                        
                        # 执行移动
                        pieces_copy[piece_index] = [to_x, to_y]
                        
                        # 检查移动后是否会让自己被将军（送将）
                        if not is_in_check(pieces_copy, color, _check_depth=1):
                            move_str = f"{from_x}{from_y}{to_x}{to_y}"
                            valid_moves.append({
                                'move': move_str,
                                'piece_index': piece_index,
                                'piece_type': piece_type,
                                'from': [from_x, from_y],
                                'to': [to_x, to_y]
                            })
    
    return valid_moves

def check_game_status(pieces, current_player):
    """检查游戏状态"""
    current_in_check = is_in_check(pieces, current_player, _check_depth=0)
    current_valid_moves = get_all_valid_moves(pieces, current_player, _move_depth=0)
    
    if current_in_check and len(current_valid_moves) == 0:
        # 被将军且无子可走 = 将死
        winner = 'black' if current_player == 'red' else 'red'
        winner_text = '黑方' if winner == 'black' else '红方'
        current_text = '红方' if current_player == 'red' else '黑方'
        
        return {
            'status': 'checkmate',
            'winner': winner,
            'message': f'{current_text}被将死，{winner_text}获胜！',
            'in_check': True,
            'valid_moves_count': 0
        }
    
    elif not current_in_check and len(current_valid_moves) == 0:
        # 未被将军但无子可走 = 困毙
        winner = 'black' if current_player == 'red' else 'red'
        winner_text = '黑方' if winner == 'black' else '红方'
        current_text = '红方' if current_player == 'red' else '黑方'
        
        return {
            'status': 'stalemate',
            'winner': winner,
            'message': f'{current_text}困毙（无子可走），{winner_text}获胜！',
            'in_check': False,
            'valid_moves_count': 0
        }
    
    elif current_in_check:
        # 被将军但有子可走 = 将军
        current_text = '红方' if current_player == 'red' else '黑方'
        return {
            'status': 'check',
            'winner': None,
            'message': f'{current_text}被将军！',
            'in_check': True,
            'valid_moves_count': len(current_valid_moves)
        }
    
    else:
        # 正常游戏状态
        return {
            'status': 'playing',
            'winner': None,
            'message': '游戏进行中',
            'in_check': False,
            'valid_moves_count': len(current_valid_moves)
        }

def is_valid_piece_move(piece_type, from_x, from_y, to_x, to_y, color, pieces):
    """检查特定棋子类型的移动是否合法"""
    dx = abs(to_x - from_x)
    dy = abs(to_y - from_y)
    
    # 不能移动到原位置
    if from_x == to_x and from_y == to_y:
        return False
    
    if piece_type == '车':
        # 车：横竖移动
        if dx != 0 and dy != 0:
            return False
        return is_path_clear(from_x, from_y, to_x, to_y, pieces)
    
    elif piece_type == '马':
        # 马：日字形移动
        if (dx == 2 and dy == 1) or (dx == 1 and dy == 2):
            # 检查马腿是否被绊
            if dx == 2:
                leg_x = from_x + (1 if to_x > from_x else -1)
                leg_y = from_y
            else:
                leg_x = from_x
                leg_y = from_y + (1 if to_y > from_y else -1)
            
            # 检查马腿位置是否有棋子
            for piece in pieces:
                if is_piece_alive(piece) and piece[0] == leg_x and piece[1] == leg_y:
                    return False
            return True
        return False
    
    elif piece_type in ['相', '象']:
        # 相/象：田字形移动，不能过河
        if dx != 2 or dy != 2:
            return False
        
        # 检查是否过河
        if crossed_river(to_y, color):
            return False
        
        # 检查象眼是否被堵
        eye_x = from_x + (to_x - from_x) // 2
        eye_y = from_y + (to_y - from_y) // 2
        for piece in pieces:
            if is_piece_alive(piece) and piece[0] == eye_x and piece[1] == eye_y:
                return False
        return True
    
    elif piece_type in ['仕', '士']:
        # 仕/士：九宫格内斜向移动
        if dx != 1 or dy != 1:
            return False
        return is_in_palace(to_x, to_y, color)
    
    elif piece_type in ['帅', '将']:
        # 帅/将移动规则
        # 首先检查目标位置是否在九宫格内
        if not is_in_palace(to_x, to_y, color):
            return False
        
        # 检查移动距离：只能移动一格
        if not ((dx == 1 and dy == 0) or (dx == 0 and dy == 1)):
            return False
        
        # 检查飞将规则（专门针对将/帅移动）
        if not check_flying_general_for_king_move(pieces, from_x, from_y, to_x, to_y, color):
            return False
        
        return True
    
    elif piece_type == '炮':
        # 炮：横竖移动，吃子需要炮台
        if dx != 0 and dy != 0:
            return False
        
        # 检查目标位置是否有棋子
        target_has_piece = False
        for piece in pieces:
            if is_piece_alive(piece) and piece[0] == to_x and piece[1] == to_y:
                target_has_piece = True
                break
        
        if target_has_piece:
            # 吃子：需要中间有且仅有一个棋子作为炮台
            return count_pieces_between(from_x, from_y, to_x, to_y, pieces) == 1
        else:
            # 移动：路径必须畅通
            return is_path_clear(from_x, from_y, to_x, to_y, pieces)
    
    elif piece_type in ['兵', '卒']:
        # 兵/卒：向前一格，过河后可横向移动
        if color == 'red':
            # 红兵
            if not crossed_river(from_y, color):
                # 未过河：只能向前
                return (dx == 0 and dy == 1 and to_y == from_y - 1)
            else:
                # 已过河：可以向前或横向
                forward_move = (dx == 0 and dy == 1 and to_y == from_y - 1)
                sideways_move = (dx == 1 and dy == 0)
                return forward_move or sideways_move
        else:  # black
            # 黑卒
            if not crossed_river(from_y, color):
                # 未过河：只能向前
                return (dx == 0 and dy == 1 and to_y == from_y + 1)
            else:
                # 已过河：可以向前或横向
                forward_move = (dx == 0 and dy == 1 and to_y == from_y + 1)
                sideways_move = (dx == 1 and dy == 0)
                return forward_move or sideways_move
    
    return False

def is_path_clear(from_x, from_y, to_x, to_y, pieces):
    """检查两点之间的路径是否清空"""
    step_x = 0 if from_x == to_x else (1 if to_x > from_x else -1)
    step_y = 0 if from_y == to_y else (1 if to_y > from_y else -1)
    
    x, y = from_x + step_x, from_y + step_y
    while x != to_x or y != to_y:
        for piece in pieces:
            if is_piece_alive(piece) and piece[0] == x and piece[1] == y:
                return False
        x += step_x
        y += step_y
    return True

def count_pieces_between(from_x, from_y, to_x, to_y, pieces):
    """计算两点之间的棋子数量"""
    step_x = 0 if from_x == to_x else (1 if to_x > from_x else -1)
    step_y = 0 if from_y == to_y else (1 if to_y > from_y else -1)
    
    count = 0
    x, y = from_x + step_x, from_y + step_y
    while x != to_x or y != to_y:
        for piece in pieces:
            if is_piece_alive(piece) and piece[0] == x and piece[1] == y:
                count += 1
        x += step_x
        y += step_y
    return count

def is_move_legal_for_player(state, move, player_color):
    """检查移动是否合法 - 增强飞将检查"""
    try:
        if not validate_move(move):
            return False
        
        from_x, from_y, to_x, to_y = [int(char) for char in move]
        pieces = get_pieces_from_state(state)
        
        # 查找移动的棋子
        moving_piece_index = -1
        moving_piece_type = None
        for piece_index, piece_position in enumerate(pieces):
            if (piece_position[0] == from_x and piece_position[1] == from_y and 
                is_piece_alive(piece_position)):
                piece_color = get_piece_color_by_index(piece_index)
                if piece_color == player_color:
                    moving_piece_index = piece_index
                    moving_piece_type = get_piece_type_by_index(piece_index)
                    break
                else:
                    return False
        
        if moving_piece_index == -1:
            return False
        
        # 检查被将军时的特殊限制
        currently_in_check = is_in_check(pieces, player_color, _check_depth=1)
        if currently_in_check:
            # 如果是将/帅的移动，必须在九宫格内
            if moving_piece_type in ['帅', '将']:
                if not is_in_palace(to_x, to_y, player_color):
                    return False
        
        # 检查目标位置是否有己方棋子
        for piece_index, piece_position in enumerate(pieces):
            if (piece_position[0] == to_x and piece_position[1] == to_y and 
                is_piece_alive(piece_position)):
                target_piece_color = get_piece_color_by_index(piece_index)
                if target_piece_color == player_color:
                    return False
        
        # 检查棋子移动规则
        if not is_valid_piece_move(moving_piece_type, from_x, from_y, to_x, to_y, player_color, pieces):
            return False
        
        # 检查移动后是否会导致飞将（适用于所有棋子）
        if not check_flying_general_after_move(pieces, moving_piece_index, from_x, from_y, to_x, to_y):
            return False
        
        # 模拟移动后检查是否会导致送将
        pieces_copy = [pos[:] for pos in pieces]
        
        # 移除被吃的棋子
        for other_index, other_pos in enumerate(pieces_copy):
            if (other_index != moving_piece_index and 
                is_piece_alive(other_pos) and 
                other_pos[0] == to_x and other_pos[1] == to_y):
                pieces_copy[other_index] = [9, 9]
                break
        
        # 执行移动
        pieces_copy[moving_piece_index] = [to_x, to_y]
        
        # 检查移动后是否会让己方被将军
        if is_in_check(pieces_copy, player_color, _check_depth=1):
            return False
        
        return True
        
    except Exception as e:
        print(f"❌ 检查移动合法性时出错: {e}")
        return False

def apply_move_to_state(state, move):
    """将移动应用到状态字符串，返回新状态"""
    try:
        if not validate_move(move):
            raise ValueError(f"无效的移动: {move}")
        
        from_x, from_y, to_x, to_y = [int(char) for char in move]
        pieces = get_pieces_from_state(state)
        
        # 查找要移动的棋子
        piece_index = -1
        for i, piece in enumerate(pieces):
            if piece[0] == from_x and piece[1] == from_y and is_piece_alive(piece):
                piece_index = i
                break
        
        if piece_index == -1:
            raise ValueError(f"在位置 ({from_x},{from_y}) 没有找到活跃棋子")
        
        # 移除被吃的棋子
        for i, piece in enumerate(pieces):
            if piece[0] == to_x and piece[1] == to_y and i != piece_index and is_piece_alive(piece):
                pieces[i] = [9, 9]
                break
        
        # 移动棋子
        pieces[piece_index] = [to_x, to_y]
        
        # 生成新状态字符串
        new_state = ''
        for piece in pieces:
            new_state += str(piece[0]) + str(piece[1])
        
        return new_state
        
    except Exception as e:
        print(f"❌ 应用移动时出错: {e}")
        raise

# ===== REST API 路由 =====

@app.route('/api/v1/games', methods=['POST'])
def create_game():
    """创建新游戏 - REST风格"""
    try:
        data = request.get_json() or {}
        
        # 使用现有的初始化逻辑
        game_data = {
            "id": str(uuid.uuid4()),
            "board_state": "8979695949392919097717866646260600102030405060708012720323436383",
            "current_player": "red",
            "game_status": {
                "status": "playing",
                "winner": None,
                "message": "游戏开始",
                "in_check": False
            },
            "mode": data.get("mode", "human_vs_ai"),
            "player_color": data.get("player_color", "red"),
            "created_at": datetime.now().isoformat(),
            "updated_at": datetime.now().isoformat()
        }
        
        return jsonify({
            "success": True,
            "data": game_data
        }), 201
        
    except Exception as e:
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@app.route('/api/v1/games/<game_id>', methods=['GET'])
def get_game(game_id):
    """获取游戏状态 - REST风格"""
    try:
        # 这里可以从数据库获取游戏状态
        # 暂时返回默认状态
        game_data = {
            "id": game_id,
            "board_state": "8979695949392919097717866646260600102030405060708012720323436383",
            "current_player": "red",
            "game_status": {
                "status": "playing",
                "winner": None,
                "message": "游戏进行中",
                "in_check": False
            },
            "mode": "human_vs_ai",
            "updated_at": datetime.now().isoformat()
        }
        
        return jsonify({
            "success": True,
            "data": game_data
        }), 200
        
    except Exception as e:
        return jsonify({
            "success": False,
            "error": str(e)
        }), 404

@app.route('/api/v1/games/<game_id>/moves', methods=['POST'])
def make_player_move(game_id):
    """玩家移动 - 整合原有的 /player_move/ 逻辑"""
    if request.method == 'OPTIONS':
        return jsonify({'success': True}), 200
    
    try:
        data = request.json
        if not data:
            return jsonify({
                'success': False,
                'error': '请求数据为空'
            }), 400
            
        # 提取REST风格的数据格式
        board_state = data.get('board_state')
        move = data.get('move')
        player_color = data.get('color', 'red')
        
        # 如果是新格式，转换为旧格式
        if 'from' in data and 'to' in data:
            from_pos = data['from']
            to_pos = data['to']
            move = f"{from_pos['x']}{from_pos['y']}{to_pos['x']}{to_pos['y']}"
            board_state = data.get('board_state', "8979695949392919097717866646260600102030405060708012720323436383")
        
        # 复用现有的移动验证逻辑
        if not validate_move(move):
            return jsonify({
                'success': False,
                'error': f'无效的移动格式: {move}'
            }), 400
        
        if not is_move_legal_for_player(board_state, move, player_color):
            return jsonify({
                'success': False,
                'error': '移动不合法：请检查是否符合象棋走法规则'
            }), 400
        
        try:
            new_state = apply_move_to_state(board_state, move)
            pieces = get_pieces_from_state(new_state)
            
            next_player = 'black' if player_color == 'red' else 'red'
            game_status = check_game_status(pieces, next_player)
            
            # 保存移动数据
            add_game_state(board_state, move)
            
            return jsonify({
                'success': True,
                'data': {
                    'game_id': game_id,
                    'move': {
                        'from': {'x': int(move[0]), 'y': int(move[1])},
                        'to': {'x': int(move[2]), 'y': int(move[3])},
                        'raw': move
                    },
                    'new_board_state': new_state,
                    'current_player': next_player,
                    'game_status': game_status,
                    'message': f'{player_color}方移动成功',
                    'updated_at': datetime.now().isoformat()
                }
            }), 200
            
        except Exception as e:
            return jsonify({
                'success': False,
                'error': f'移动处理失败: {str(e)}'
            }), 500
        
    except Exception as e:
        return jsonify({
            'success': False,
            'error': f'服务器错误: {str(e)}'
        }), 500

@app.route('/api/v1/games/<game_id>/ai-move', methods=['POST'])
def make_ai_move(game_id):
    """AI移动 - 整合原有的 /move/<state> 逻辑"""
    try:
        data = request.get_json() or {}
        state = data.get('board_state', "8979695949392919097717866646260600102030405060708012720323436383")
        
        chess_data = load_chess_data(state=state)
        if not chess_data:
            return jsonify({
                'success': False,
                'error': 'no_chess_data',
                'message': '没有棋谱数据，请玩家控制黑方',
                'data': {
                    'player_mode': True,
                    'next_player': 'black'
                }
            }), 404
        
        ai_color = 'black'
        best_move = None
        
        # 复用原有的AI逻辑
        for entry in chess_data:
            if entry.state == state:
                if entry.best_move:
                    candidate_move = entry.best_move
                    if (validate_move(candidate_move) and 
                        is_move_legal_for_player(state, candidate_move, ai_color)):
                        best_move = candidate_move
                        break
                
                if not best_move and hasattr(entry, 'move_counts') and entry.move_counts:
                    try:
                        if isinstance(entry.move_counts, str):
                            move_counts = json.loads(entry.move_counts)
                        else:
                            move_counts = entry.move_counts
                        
                        valid_moves = []
                        for move in move_counts.keys():
                            if (validate_move(move) and 
                                is_move_legal_for_player(state, move, ai_color)):
                                valid_moves.append((move, move_counts[move]))
                        
                        if valid_moves:
                            best_move = max(valid_moves, key=lambda x: x[1])[0]
                            break
                    except (json.JSONDecodeError, AttributeError):
                        pass
                break
        
        if not best_move:
            return jsonify({
                'success': False,
                'error': 'no_valid_move',
                'message': '数据库中没有找到合法移动，请玩家控制黑方',
                'data': {
                    'player_mode': True,
                    'next_player': 'black'
                }
            }), 404
        
        try:
            new_state = apply_move_to_state(state, best_move)
            pieces = get_pieces_from_state(new_state)
            
            next_player = 'red'
            game_status = check_game_status(pieces, next_player)
            
            return jsonify({
                'success': True,
                'data': {
                    'game_id': game_id,
                    'move': {
                        'from': {'x': int(best_move[0]), 'y': int(best_move[1])},
                        'to': {'x': int(best_move[2]), 'y': int(best_move[3])},
                        'raw': best_move
                    },
                    'new_board_state': new_state,
                    'current_player': next_player,
                    'game_status': game_status,
                    'message': 'AI移动成功',
                    'strategy': 'book',
                    'updated_at': datetime.now().isoformat()
                }
            }), 200
            
        except Exception as e:
            return jsonify({
                'success': False,
                'error': f'AI无法执行移动: {str(e)}'
            }), 500
    
    except Exception as e:
        return jsonify({
            'success': False,
            'error': f'服务器内部错误: {str(e)}'
        }), 500

@app.route('/api/v1/games/<game_id>/valid-moves', methods=['GET'])
def get_valid_moves(game_id):
    """获取指定棋子的合法移动 - 修复版本"""
    try:
        # 添加详细的参数验证和错误处理
        piece_x = request.args.get('piece_x')
        piece_y = request.args.get('piece_y')
        
        # 调试信息
        print(f"🔍 获取合法移动请求: game_id={game_id}, piece_x={piece_x}, piece_y={piece_y}")
        print(f"📋 完整请求参数: {dict(request.args)}")
        
        # 参数验证
        if piece_x is None:
            print("❌ 缺少 piece_x 参数")
            return jsonify({
                'success': False,
                'error': 'Missing required parameter: piece_x'
            }), 400
            
        if piece_y is None:
            print("❌ 缺少 piece_y 参数")
            return jsonify({
                'success': False,
                'error': 'Missing required parameter: piece_y'
            }), 400
        
        # 类型转换和范围验证
        try:
            piece_x = int(piece_x)
            piece_y = int(piece_y)
        except ValueError:
            print(f"❌ 参数类型错误: piece_x={piece_x}, piece_y={piece_y}")
            return jsonify({
                'success': False,
                'error': 'Parameters piece_x and piece_y must be integers'
            }), 400
        
        # 范围验证
        if not (0 <= piece_x <= 8):
            print(f"❌ piece_x 超出范围: {piece_x}")
            return jsonify({
                'success': False,
                'error': 'piece_x must be between 0 and 8'
            }), 400
            
        if not (0 <= piece_y <= 9):
            print(f"❌ piece_y 超出范围: {piece_y}")
            return jsonify({
                'success': False,
                'error': 'piece_y must be between 0 and 9'
            }), 400
        
        # 获取棋盘状态
        board_state = request.args.get('board_state', "8979695949392919097717866646260600102030405060708012720323436383")
        
        print(f"✅ 参数验证通过: piece_x={piece_x}, piece_y={piece_y}")
        
        # 检查是否有完整的游戏逻辑函数
        try:
            # 获取棋盘状态
            pieces = get_pieces_from_state(board_state)
            
            # 找到指定位置的棋子
            piece_index = -1
            piece_type = None
            piece_color = None
            
            for i, piece in enumerate(pieces):
                if piece[0] == piece_x and piece[1] == piece_y and is_piece_alive(piece):
                    piece_index = i
                    piece_type = get_piece_type_by_index(i)
                    piece_color = get_piece_color_by_index(i)
                    break
            
            if piece_index == -1:
                print(f"❌ 指定位置没有棋子: ({piece_x}, {piece_y})")
                return jsonify({
                    'success': False,
                    'error': f'No piece found at position ({piece_x}, {piece_y})'
                }), 400
            
            print(f"🎯 找到棋子: 索引={piece_index}, 类型={piece_type}, 颜色={piece_color}")
            
            # 计算合法移动
            valid_moves = []
            for to_x in range(9):
                for to_y in range(10):
                    if is_valid_piece_move(piece_type, piece_x, piece_y, to_x, to_y, piece_color, pieces):
                        # 检查目标位置是否被己方棋子占据
                        target_occupied_by_self = False
                        for other_index, other_pos in enumerate(pieces):
                            if (other_index != piece_index and 
                                is_piece_alive(other_pos) and 
                                other_pos[0] == to_x and other_pos[1] == to_y and
                                get_piece_color_by_index(other_index) == piece_color):
                                target_occupied_by_self = True
                                break
                        
                        if not target_occupied_by_self:
                            # 检查移动后是否会导致飞将或送将
                            if check_flying_general_after_move(pieces, piece_index, piece_x, piece_y, to_x, to_y):
                                # 模拟移动检查是否会送将
                                pieces_copy = [pos[:] for pos in pieces]
                                
                                # 移除被吃的棋子
                                for other_index, other_pos in enumerate(pieces_copy):
                                    if (other_index != piece_index and 
                                        is_piece_alive(other_pos) and 
                                        other_pos[0] == to_x and other_pos[1] == to_y):
                                        pieces_copy[other_index] = [9, 9]
                                        break
                                
                                # 执行移动
                                pieces_copy[piece_index] = [to_x, to_y]
                                
                                # 检查移动后是否会让自己被将军
                                if not is_in_check(pieces_copy, piece_color, _check_depth=1):
                                    valid_moves.append({'x': to_x, 'y': to_y})
            
            print(f"✅ 计算完成，找到 {len(valid_moves)} 个合法移动")
            
            return jsonify({
                'success': True,
                'data': {
                    'piece': {'x': piece_x, 'y': piece_y, 'type': piece_type, 'color': piece_color},
                    'valid_moves': valid_moves
                }
            }), 200
            
        except NameError as e:
            # 如果游戏逻辑函数不存在，返回简单的示例移动
            print(f"⚠️ 游戏逻辑函数不存在: {e}")
            print("🔄 使用简化逻辑")
            
            # 返回一些示例合法移动（用于测试）
            valid_moves = []
            
            # 基本移动（上下左右）
            directions = [
                {'x': piece_x, 'y': piece_y - 1},  # 上
                {'x': piece_x, 'y': piece_y + 1},  # 下
                {'x': piece_x - 1, 'y': piece_y},  # 左
                {'x': piece_x + 1, 'y': piece_y}   # 右
            ]
            
            for move in directions:
                # 检查边界
                if 0 <= move['x'] <= 8 and 0 <= move['y'] <= 9:
                    valid_moves.append(move)
            
            return jsonify({
                'success': True,
                'data': {
                    'piece': {'x': piece_x, 'y': piece_y, 'type': 'unknown', 'color': 'unknown'},
                    'valid_moves': valid_moves
                }
            }), 200
        
    except Exception as e:
        print(f"❌ get_valid_moves 发生异常: {e}")
        import traceback
        traceback.print_exc()
        
        return jsonify({
            'success': False,
            'error': f'Internal server error: {str(e)}'
        }), 500

@app.route('/api/v1/games/<game_id>', methods=['PUT'])
def update_game(game_id):
    """更新游戏状态（暂停、继续等）"""
    try:
        data = request.get_json()
        action = data.get('action')
        
        if action not in ['pause', 'resume', 'reset']:
            return jsonify({
                'success': False,
                'error': 'Invalid action'
            }), 400
        
        # 执行相应动作
        if action == 'reset':
            updated_game = {
                "id": game_id,
                "board_state": "8979695949392919097717866646260600102030405060708012720323436383",
                "current_player": "red",
                "game_status": {
                    "status": "playing",
                    "winner": None,
                    "message": "游戏重新开始",
                    "in_check": False
                },
                "mode": "human_vs_ai",
                "updated_at": datetime.now().isoformat()
            }
        else:
            updated_game = {
                "id": game_id,
                "status": "paused" if action == "pause" else "playing",
                "updated_at": datetime.now().isoformat()
            }
        
        return jsonify({
            'success': True,
            'data': updated_game
        }), 200
        
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/v1/games/<game_id>', methods=['DELETE'])
def delete_game(game_id):
    """删除游戏"""
    try:
        # 这里可以从数据库删除游戏记录
        
        return jsonify({
            'success': True,
            'message': 'Game deleted successfully'
        }), 200
        
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/v1/chess-database', methods=['GET'])
def get_chess_database():
    """获取棋谱数据库"""
    try:
        state = request.args.get('state')
        limit = request.args.get('limit', 10, type=int)
        offset = request.args.get('offset', 0, type=int)
        
        chess_data = load_chess_data(state=state)
        
        # 简单的分页
        start = offset
        end = offset + limit
        paginated_data = chess_data[start:end] if chess_data else []
        
        result = []
        for move in paginated_data:
            move_counts = json.loads(move.move_counts) if isinstance(move.move_counts, str) else move.move_counts
            result.append({
                "state": move.state,
                "best_move": move.best_move,
                "move_counts": move_counts
            })
        
        return jsonify({
            'success': True,
            'data': {
                'moves': result,
                'total': len(chess_data),
                'limit': limit,
                'offset': offset
            }
        }), 200
        
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

@app.route('/api/v1/system/status', methods=['GET'])
def get_system_status():
    """系统状态 - 重构原有的 /status"""
    chess_data = load_chess_data()
    return jsonify({
        'success': True,
        'data': {
            'status': 'running',
            'chess_data_loaded': len(chess_data) > 0,
            'total_states': len(chess_data),
            'data_source': 'database',
            'database_file': 'database.db',
            'server_port': 5000,
            'api_version': 'v1',
            'features': [
                'rest_architecture',
                'flying_general_rule',
                'strict_king_movement',
                'complete_xiangqi_rules',
                'checkmate_stalemate_detection'
            ],
            'message': '象棋AI服务器运行正常（REST架构）'
        }
    }), 200

@app.route('/api/v1/system/debug/<state>', methods=['GET'])
def debug_game_state(state):
    """调试接口 - 重构原有的 /debug/<state>"""
    try:
        pieces = get_pieces_from_state(state)
        piece_info = []
        red_pieces = []
        black_pieces = []
        
        for i, piece in enumerate(pieces):
            x, y = piece
            alive = is_piece_alive(piece)
            color = get_piece_color_by_index(i)
            piece_type = get_piece_type_by_index(i) if alive else 'dead'
            
            piece_data = {
                'index': i, 
                'x': x, 
                'y': y, 
                'alive': alive,
                'color': color,
                'type': piece_type
            }
            piece_info.append(piece_data)
            
            if alive:
                if color == 'red':
                    red_pieces.append(piece_data)
                else:
                    black_pieces.append(piece_data)
        
        red_status = check_game_status(pieces, 'red')
        black_status = check_game_status(pieces, 'black')
        red_moves = get_all_valid_moves(pieces, 'red', _move_depth=0)
        black_moves = get_all_valid_moves(pieces, 'black', _move_depth=0)
        
        return jsonify({
            'success': True,
            'data': {
                'state': state,
                'length': len(state),
                'pieces': piece_info,
                'statistics': {
                    'red_pieces': len(red_pieces),
                    'black_pieces': len(black_pieces),
                    'red_valid_moves': len(red_moves),
                    'black_valid_moves': len(black_moves)
                },
                'game_status': {
                    'red': red_status,
                    'black': black_status
                },
                'sample_moves': {
                    'red': red_moves[:5] if red_moves else [],
                    'black': black_moves[:5] if black_moves else []
                }
            }
        }), 200
        
    except Exception as e:
        return jsonify({
            'success': False,
            'error': str(e)
        }), 500

# ===== 向后兼容的旧路由 =====
# 保持旧接口可用，避免破坏现有前端

@app.route('/')
def serve_html():
    return render_template('chess.html')

@app.route('/move/<state>')
def old_get_move(state):
    """向后兼容：旧的AI移动接口"""
    try:
        chess_data = load_chess_data(state=state)
        if not chess_data:
            return jsonify({
                'error': 'no_chess_data',
                'message': '没有棋谱数据，请玩家控制黑方',
                'player_mode': True,
                'next_player': 'black'
            }), 404
        
        ai_color = 'black'
        best_move = None
        
        for entry in chess_data:
            if entry.state == state:
                if entry.best_move:
                    candidate_move = entry.best_move
                    if (validate_move(candidate_move) and 
                        is_move_legal_for_player(state, candidate_move, ai_color)):
                        best_move = candidate_move
                        break
                
                if not best_move and hasattr(entry, 'move_counts') and entry.move_counts:
                    try:
                        if isinstance(entry.move_counts, str):
                            move_counts = json.loads(entry.move_counts)
                        else:
                            move_counts = entry.move_counts
                        
                        valid_moves = []
                        for move in move_counts.keys():
                            if (validate_move(move) and 
                                is_move_legal_for_player(state, move, ai_color)):
                                valid_moves.append((move, move_counts[move]))
                        
                        if valid_moves:
                            best_move = max(valid_moves, key=lambda x: x[1])[0]
                            break
                    except (json.JSONDecodeError, AttributeError):
                        pass
                break
        
        if not best_move:
            return jsonify({
                'error': 'no_valid_move',
                'message': '数据库中没有找到合法移动，请玩家控制黑方',
                'player_mode': True,
                'next_player': 'black'
            }), 404
        
        try:
            new_state = apply_move_to_state(state, best_move)
            pieces = get_pieces_from_state(new_state)
            
            next_player = 'red'
            game_status = check_game_status(pieces, next_player)
            
            return jsonify({
                'move': best_move,
                'new_state': new_state,
                'message': 'AI移动成功（基于数据库）',
                'strategy': 'book',
                'game_status': game_status
            })
        except Exception as e:
            return jsonify({
                'error': f'AI无法执行移动: {str(e)}'
            }), 500
    
    except Exception as e:
        print(f"❌ 处理AI移动请求时出错: {e}")
        return jsonify({
            'error': f'服务器内部错误: {str(e)}'
        }), 500

@app.route('/player_move/', methods=['POST', 'OPTIONS'])
def old_player_move():
    """向后兼容：旧的玩家移动接口"""
    if request.method == 'OPTIONS':
        response = jsonify({'status': 'ok'})
        response.headers.add('Access-Control-Allow-Origin', '*')
        response.headers.add('Access-Control-Allow-Headers', 'Content-Type')
        response.headers.add('Access-Control-Allow-Methods', 'POST, OPTIONS')
        return response
    
    try:
        data = request.json
        
        if not data:
            return jsonify({
                'valid': False,
                'message': '请求数据为空'
            }), 400
            
        board_state = data.get('board')
        move = data.get('move')
        player_color = data.get('color', 'red')
        
        if not board_state or not move:
            return jsonify({
                'valid': False,
                'message': '缺少board或move参数'
            }), 400
        
        if not validate_move(move):
            return jsonify({
                'valid': False,
                'message': f'无效的移动格式: {move}'
            })
        
        if not is_move_legal_for_player(board_state, move, player_color):
            return jsonify({
                'valid': False,
                'message': f'移动不合法：请检查是否符合象棋走法规则'
            })
        
        try:
            new_state = apply_move_to_state(board_state, move)
            pieces = get_pieces_from_state(new_state)
            
            next_player = 'black' if player_color == 'red' else 'red'
            game_status = check_game_status(pieces, next_player)
            
            add_game_state(board_state, move)
            
            return jsonify({
                'valid': True,
                'new_state': new_state,
                'message': f'{player_color}方移动成功',
                'game_status': game_status
            })
        except Exception as e:
            return jsonify({
                'valid': False,
                'message': f'移动处理失败: {str(e)}'
            })
        
    except Exception as e:
        print(f"❌ 处理玩家移动请求时出错: {e}")
        return jsonify({
            'valid': False,
            'message': f'服务器错误: {str(e)}'
        }), 500

@app.route('/status')
def old_status():
    """向后兼容：旧的状态接口"""
    chess_data = load_chess_data()
    return jsonify({
        'status': 'running',
        'chess_data_loaded': len(chess_data) > 0,
        'total_states': len(chess_data),
        'data_source': 'database',
        'database_file': 'database.db',
        'server_port': 5000,
        'features': [
            'flying_general_rule',
            'strict_king_movement',
            'optimized_debug_output',
            'complete_xiangqi_rules'
        ],
        'message': '象棋AI服务器运行正常（修复飞将规则，优化调试输出）'
    })

@app.route('/debug/<state>')
def old_debug_state(state):
    """向后兼容：旧的调试接口"""
    try:
        pieces = get_pieces_from_state(state)
        piece_info = []
        red_pieces = []
        black_pieces = []
        
        for i, piece in enumerate(pieces):
            x, y = piece
            alive = is_piece_alive(piece)
            color = get_piece_color_by_index(i)
            piece_type = get_piece_type_by_index(i) if alive else 'dead'
            
            piece_data = {
                'index': i, 
                'x': x, 
                'y': y, 
                'alive': alive,
                'color': color,
                'type': piece_type
            }
            piece_info.append(piece_data)
            
            if alive:
                if color == 'red':
                    red_pieces.append(piece_data)
                else:
                    black_pieces.append(piece_data)
        
        red_status = check_game_status(pieces, 'red')
        black_status = check_game_status(pieces, 'black')
        red_moves = get_all_valid_moves(pieces, 'red', _move_depth=0)
        black_moves = get_all_valid_moves(pieces, 'black', _move_depth=0)
        
        return jsonify({
            'state': state,
            'length': len(state),
            'pieces': piece_info,
            'red_pieces': red_pieces,
            'black_pieces': black_pieces,
            'total_red_pieces': len(red_pieces),
            'total_black_pieces': len(black_pieces),
            'red_game_status': red_status,
            'black_game_status': black_status,
            'red_valid_moves': len(red_moves),
            'black_valid_moves': len(black_moves),
            'red_moves_sample': red_moves[:5] if red_moves else [],
            'black_moves_sample': black_moves[:5] if black_moves else []
        })
    except Exception as e:
        return jsonify({
            'error': str(e),
            'state': state
        }), 500

@app.route('/test')
def test():
    """测试接口"""
    chess_data = load_chess_data()
    return jsonify({
        'message': '服务器连接正常',
        'chess_data_count': len(chess_data),
        'features': [
            'rest_architecture',
            'flying_general_rule',
            'optimized_performance',
            'complete_xiangqi_rules'
        ]
    })

# ===== 错误处理 =====
@app.errorhandler(404)
def not_found(error):
    return jsonify({
        'success': False,
        'error': 'Resource not found'
    }), 404

@app.errorhandler(500)
def internal_error(error):
    return jsonify({
        'success': False,
        'error': 'Internal server error'
    }), 500

if __name__ == '__main__':
    print("🚀 正在启动象棋AI服务器（REST架构）...")
    print("📂 初始化数据库...")
    
    # 初始化数据库
    init_database()
    
    # 加载棋谱数据
    chess_data = load_chess_data()
    if chess_data:
        print("✅ 棋谱数据加载成功")
    else:
        print("⚠️ 棋谱数据加载失败，进入玩家控制模式")
    
    print("🎮 功能特性:")
    print("   - ✅ REST API架构")
    print("   - ✅ 统一响应格式")
    print("   - ✅ 资源化URL设计")
    print("   - ✅ 向后兼容传统API")
    print("   - ✈️ 飞将规则：禁止将帅对面且中间无子")
    print("   - 👑 严格帅/将移动规则（只能走一格，不能出九宫格）")
    print("   - 🔒 被将军时的移动限制")
    print("   - 💀 将死和困毙判定")
    print("   - 🛡️ 送将检测")
    print("   - 📝 数据收集")
    
    print("🆕 REST API端点:")
    print("   - POST   /api/v1/games - 创建游戏")
    print("   - GET    /api/v1/games/{id} - 获取游戏状态")
    print("   - POST   /api/v1/games/{id}/moves - 玩家移动")
    print("   - POST   /api/v1/games/{id}/ai-move - AI移动")
    print("   - GET    /api/v1/games/{id}/valid-moves - 获取合法移动")
    print("   - PUT    /api/v1/games/{id} - 更新游戏状态")
    print("   - DELETE /api/v1/games/{id} - 删除游戏")
    print("   - GET    /api/v1/chess-database - 获取棋谱数据")
    print("   - GET    /api/v1/system/status - 系统状态")
    print("   - GET    /api/v1/system/debug/{state} - 调试信息")
    
    print("🔄 兼容接口:")
    print("   - GET    /move/{state} - 传统AI移动")
    print("   - POST   /player_move/ - 传统玩家移动")
    print("   - GET    /status - 传统系统状态")
    print("   - GET    /debug/{state} - 传统调试")
    
    print("🌐 服务器启动:")
    print("   - 地址: http://0.0.0.0:5000")
    print("   - 端口: 5000")
    print("   - API版本: v1")
    
    try:
        app.run(host='0.0.0.0', port=5000, debug=True)
    except Exception as e:
        print(f"❌ 服务器启动失败: {e}")
    finally:
        session.close()



